<template>
  <div :class="['baseFrom']">
    <el-form v-if="!propKey" ref="formRef" :rules="rules" :model="data" :scroll-to-error="true"
      :validate-on-rule-change="false" @submit.native.prevent v-bind="{ ...formConfigComputed}">
      <FormItemLayout :isEditByRow="isEditByRow" :allData="allData" :rowConfig="rowConfig" :formItems="formItems" :allDisabled="allDisabled"
        :value="data" :data="data" @update:value="updateValue" :itemStyle="itemStyle" :colLayout="colLayout"
        :footerLayout="footerLayout" :hideItems="hideItems" @keyUpEnter="keyUpEnter" :tmpInfo="tmpInfo">
        <template v-for="(_, name) in $slots" #[name]="slotData">
          <slot :name="name" v-bind="slotData" />
        </template>
      </FormItemLayout>
    </el-form>
    <FormItemLayout v-if="propKey" :isEditByRow="isEditByRow" :propKey="propKey" :allData="allData" :rowConfig="rowConfig" :formItems="formItems"
      :allDisabled="allDisabled" :value="data" :data="data" @update:value="updateValue" :itemStyle="itemStyle"
      :colLayout="colLayout" :footerLayout="footerLayout" :hideItems="hideItems" @keyUpEnter="keyUpEnter" :tmpInfo="tmpInfo">
      <template v-for="(_, name) in $slots" #[name]="slotData">
        <slot :name="name" v-bind="slotData" />
      </template>
    </FormItemLayout>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

import type { FormInstance } from 'element-plus'
import type { Props, allDataType } from './types/index.ts'
import FormItemLayout from './FormItemLayout.vue'
import { assign } from 'fair-wing';

const props = withDefaults(defineProps<Props & { notLabel?: boolean }>(), {
  formConfig: () => ({}),
  data: () => ({}),
  formItems: () => ([]),
  tmpInfo: () => ({}), // 临时数据
  notLabel: false,
  isEditByRow: true
})
const {
  propKey,
  elFormConfig = {},
  allDisabled = false,
  itemStyle = { padding: '0px' },
  colLayout,
  footerLayout = {},
  rules = {},
  rowConfig = {},
  hideItems = [],
} = props
const {formConfig, data, formItems, tmpInfo, notLabel, isEditByRow } = toRefs(props)

const emits = defineEmits(['keyUpEnter', 'update:data'])
const formRef = ref<FormInstance>()

const formConfigComputed = computed(() => {
  return assign({}, elFormConfig, formConfig.value) as any
})


const allData = reactive<allDataType>({
  allRefs: {},
  allFormItemRefs: {},
  allEvent: {},
  allChangeData: {}
})

let getFormValidate = (): Promise<boolean> => {
  return new Promise((resolve) => {
    formRef.value?.validate((valid) => {
      resolve(valid)
    })
  })
}

const keyUpEnter = ($event: any, current: any) => {
  emits('keyUpEnter', {
    event: $event,
    current,
  })
}
function updateValue(value: any, _field: string) {
  emits('update:data', value)
}
const exposeObj: { [p: string]: any } = {
  getFormValidate,
  allRefs: allData.allRefs,
  allData: allData,
  formRef,
}
const exposeData: { [p: string]: any } = reactive({})
onMounted(() => {
  if (formRef.value) {
    const formRefKeys = Object.keys(formRef.value)
    formRefKeys.forEach((key: string) => {
      exposeData[key] = (formRef.value as any)[key]
    })
  }
  const exposeObjKeys = Object.keys(exposeObj)
  exposeObjKeys.forEach((key: string) => {
    exposeData[key] = exposeObj[key]
  })
})

defineExpose(exposeData)
</script>

<style scoped lang="scss">
.baseFrom :deep(.el-form-item) .el-form-item {
  margin-bottom: v-bind('notLabel ? "0px" : "18px"');
}
</style>
